//
//  Observable.h
//  Chart
//
//  Created by Javen Wang on 6/6/13.
//
//

#ifndef __Chart__Observable__
#define __Chart__Observable__

#include "Observer.h"

#include <string>
#include <vector>
#include <map>

namespace ytx {
//    template<typename T>
//    class Observer<T>;

    template<typename T>
    class Observable
    {
    public:
        typedef Observer<T> ObserverType;
        typedef std::vector<ObserverType *> VectorObserverType;

    private:
        std::map<std::string, VectorObserverType> eventsObservers;

    public:
        virtual void on(std::string, ObserverType *);
        virtual void off(std::string, ObserverType *);
        virtual void fire(std::string, void *);
        virtual void clear();

    protected:
        virtual T * getObservable() = 0;
    };
}

template<typename T>
void ytx::Observable<T>::on(std::string name, ytx::Observable<T>::ObserverType * observer)
{
    if (name.empty()){return;}
    eventsObservers[name].push_back(observer);
}

template<typename T>
void ytx::Observable<T>::off(std::string name, ytx::Observable<T>::ObserverType * observer)
{
    std::vector<ytx::Observable<T>::ObserverType *> & observers = eventsObservers[name];
//    std::vector<ytx::Observable<T>::ObserverType *>::iterator iii;
    for (auto it = observers.begin(); it != observers.end();) {
        if (*it == observer) {
            it = observers.erase(it);
        } else {
            ++it;
        }
    }
}

template<typename T>
void ytx::Observable<T>::fire(std::string name, void * data)
{

    for (auto it = eventsObservers[name].begin(); it != eventsObservers[name].end(); ++it) {
        if (*it) {
            //为了修复线上bug，但不知道如何解决
            try {
                (*it)->handle(getObservable(), name, data);
            } catch (int error) {
                
            }
            
        }
    }
}

template<typename T>
void ytx::Observable<T>::clear()
{
    eventsObservers.clear();
}


#endif /* defined(__Chart__Observable__) */
